/*
 * ipprocess.cpp
 *
 *  Created on: 07/07/2011
 *      Author: george
 */

#include <iostream>

#include "ipprocess.h"
#include "types.h"
#include "defines.h"
#include "pcap.h"
#include "net/ethernet.h"
#include "netinet/ip.h"
#include "errors.h"

tcp_hdr_t *ipProcess::getTcp(){
	return header.tcp;
}

udp_hdr_t *ipProcess::getUdp(){
	return header.udp;
}

icmp_hdr_t *ipProcess::getICMP(){
	return header.icmp;
}

bool ipProcess::isICMPError(){
	switch (header.icmp->type ) {
		case ICMP_DEST_UNREACH:
		case ICMP_SOURCE_QUENCH:
		case ICMP_TIME_EXCEEDED:
		case ICMP_PARAMETERPROB:
			return true;
			break;

		default:
			return false;
	}

}

bool ipProcess::isICMPInformation()
{

	return !isICMPError();
}

bool ipProcess::isICMP(){
	return protocol_type == P_ICMP;
}
bool ipProcess::isUDP() {
	return protocol_type == P_UDP;
}

bool ipProcess::isTCP(){
	return protocol_type == P_TCP;
}

void ipProcess::processTcp(const ip_hdr_t *ip){
	header.tcp = (tcp_hdr_t*)((long)ip + ip->ip_hl*4 );
}

void ipProcess::processUdp(const ip_hdr_t *ip){
	header.udp = (udp_hdr_t *)((long)ip + ip->ip_hl*4 );
}

void ipProcess::processICMP(const ip_hdr_t *ip){
	header.icmp = (icmp_hdr_t *)((long)ip + ip->ip_hl*4);
}

ipProcess::ipProcess(const struct pcap_pkthdr *h,const ip_hdr_t *ip) {


	this->protocol_type = (int)ip->ip_p;

	switch (this->protocol_type) {
		case P_TCP:
			if ( h->caplen < sizeof(tcp_hdr_t) + ip->ip_hl*4 + ETHERNET_SIZE){
				throw new NoTcpHeader;
			}

			processTcp(ip);
			break;

		case P_UDP:
			if ( h->caplen < sizeof(udp_hdr_t) + ip->ip_hl*4 + ETHERNET_SIZE){
				throw new NoUdpHeader;
			}

			processUdp(ip);
			break;

		case P_ICMP:
			if ( h->caplen < sizeof(icmp_hdr_t) + ip->ip_hl*4  + ETHERNET_SIZE){
				throw new NoIcmpHeader;
			}
			processICMP(ip);
			break;
		default:
			break;
	}
}

